#include <stdint.h>
#include "BaseObj.h"
#include "air780e_common.h"
#include "dataStrs.h"
#include "luat_uart.h"
#include "luat_gpio.h"
// #define LOG __platform_printf
#define LOG


static luat_uart_t* _uart_cfg_cache[UART_MAX] = {0};
static pika_dev* _uart_dev_cache[UART_MAX] = {0};

int pika_hal_platform_UART_open(pika_dev* dev, char* name) {
    if (!((name[0] == 'U' && name[1] == 'A' && name[2] == 'R' && name[3] == 'T') || 
    (name[0] == 'u' && name[1] == 'a' && name[2] == 'r' && name[3] == 't'))) {
        return -1;
    }

    int UART_num = atoi(name + 4);
    if (UART_num >= UART_MAX || UART_num < UART_ID0){
        return -1;
    }
    // __platform_printf("UART_num:%d\n", UART_num);
    _uart_dev_cache[UART_num] = dev; // 记录 id 和 dev的对应关系，中断服务函数要用

    if (_uart_cfg_cache[UART_num] == NULL){
        luat_uart_t* _uart_cfg = pikaMalloc(sizeof(luat_uart_t));
        if (_uart_cfg == NULL){
            return -1;
        }
        _uart_cfg->id = UART_num;
        dev->platform_data = _uart_cfg;
    }
    else{
        dev->platform_data = _uart_cfg_cache[UART_num];
    }
    return 0;
    
}

int pika_hal_platform_UART_close(pika_dev* dev) {
    luat_uart_t* _uart_cfg = dev->platform_data;
    luat_uart_close(_uart_cfg->id);
    _uart_cfg_cache[_uart_cfg->id] = NULL;
    if (NULL != dev->platform_data) {
        pikaFree(dev->platform_data, sizeof(luat_uart_t));
        dev->platform_data = NULL;
    }
    return 0;
}

int pika_hal_platform_UART_read(pika_dev* dev, void* buf, size_t count) {
    luat_uart_t* _uart_cfg = (luat_uart_t*)dev->platform_data;
    int r_count;
    r_count = luat_uart_read(_uart_cfg->id, buf, count);
    // LOG("UART_read r_count:%d\n", r_count);
    return r_count;
}

int pika_hal_platform_UART_write(pika_dev* dev, void* buf, size_t count) {
    luat_uart_t* _uart_cfg = (luat_uart_t*)dev->platform_data;
    int res = luat_uart_write(_uart_cfg->id, buf, count);
    // LOG("UART_write res:%d\n", res);
    return res;
}

static void _uart_recv_cb(int uart_id, uint32_t data_len){
    pika_dev* dev = _uart_dev_cache[uart_id]; // 找回uart id 对应的 dev
    // luat_uart_t* _uart_cfg = (luat_uart_t*)dev->platform_data;
    pika_hal_UART_config* cfg = (pika_hal_UART_config*)dev->ioctl_config;
    cfg->event_callback(dev, cfg->event_callback_filter);
}

static void _uart_send_cb(int uart_id, uint32_t data_len){
    pika_dev* dev = _uart_dev_cache[uart_id]; // 找回uart id 对应的 dev
    // luat_uart_t* _uart_cfg = (luat_uart_t*)dev->platform_data;
    pika_hal_UART_config* cfg = (pika_hal_UART_config*)dev->ioctl_config;
    cfg->event_callback(dev, cfg->event_callback_filter);

}


int pika_hal_platform_UART_ioctl_config(pika_dev* dev,
                                        pika_hal_UART_config* cfg) {
    luat_uart_t* _uart_cfg = (luat_uart_t*)dev->platform_data;
    _uart_cfg->baud_rate = cfg->baudrate;
    switch (cfg->data_bits) {
        case PIKA_HAL_UART_DATA_BITS_5:
            _uart_cfg->data_bits = UART_DATA_BIT5;
            break;
        case PIKA_HAL_UART_DATA_BITS_6:
            _uart_cfg->data_bits = UART_DATA_BIT6;
            break;
        case PIKA_HAL_UART_DATA_BITS_7:
            _uart_cfg->data_bits = UART_DATA_BIT7;
            break;
        case PIKA_HAL_UART_DATA_BITS_8:
            _uart_cfg->data_bits = UART_DATA_BIT8;
            break;
        default:
            _uart_cfg->data_bits = UART_DATA_BIT8;
            break;
    }
    switch (cfg->parity) {
        case PIKA_HAL_UART_PARITY_NONE:
            _uart_cfg->parity = UART_PARITY_NONE;
            break;
        case PIKA_HAL_UART_PARITY_ODD:
            _uart_cfg->parity = UART_PARITY_ODD;
            break;
        case PIKA_HAL_UART_PARITY_EVEN:
            _uart_cfg->parity = UART_PARITY_EVEN;
            break;
        default:
            _uart_cfg->parity = UART_PARITY_NONE;
            break;
    }
    switch (cfg->stop_bits) {
        case PIKA_HAL_UART_STOP_BITS_1:
            _uart_cfg->stop_bits = UART_STOP_BIT1;
            break;
        case PIKA_HAL_UART_STOP_BITS_2:
            _uart_cfg->stop_bits = UART_STOP_BIT2;
            break;
        case PIKA_HAL_UART_STOP_BITS_1_5:
            _uart_cfg->stop_bits = UART_STOP_BIT1_5;
            break;
        default:
            _uart_cfg->stop_bits = UART_STOP_BIT1;
            break;
    }
    //好像Air780E没有流控功能
    #if 0 
    switch (cfg->flow_control) {
        case PIKA_HAL_UART_FLOW_CONTROL_NONE:
            _uart_cfg->flow_ctrl = UART_FLOWCTRL_NONE;
            break;
        case PIKA_HAL_UART_FLOW_CONTROL_CTS:
            _uart_cfg->flow_ctrl = UART_FLOWCTRL_CTS;
            break;
        case PIKA_HAL_UART_FLOW_CONTROL_RTS:
            _uart_cfg->flow_ctrl = UART_FLOWCTRL_RTS;
            break;
        case PIKA_HAL_UART_FLOW_CONTROL_RTS_CTS:
            _uart_cfg->flow_ctrl = UART_FLOWCTRL_RTS_CTS;
            break;
        default:
            _uart_cfg->flow_ctrl = UART_FLOWCTRL_NONE;
            break;
    }
    #endif
    /* support event callback */
    if (NULL != cfg->event_callback &&
        PIKA_HAL_EVENT_CALLBACK_ENA_ENABLE == cfg->event_callback_ena) {
        switch (cfg->event_callback_filter) {
            /* Configure UART to interrupt mode */
            case PIKA_HAL_UART_EVENT_SIGNAL_RX:
                luat_uart_ctrl(_uart_cfg->id, LUAT_UART_SET_RECV_CALLBACK, _uart_recv_cb);
                break;
            case PIKA_HAL_UART_EVENT_SIGNAL_TX:
                luat_uart_ctrl(_uart_cfg->id, LUAT_UART_SET_SENT_CALLBACK, _uart_send_cb);
                break;
            default:
                __platform_printf(
                    "[ERROR] not supported event callback filter %d\r\n",
                    cfg->event_callback_filter);
                return -1;
        }
    }

    if (cfg->TX != NULL && cfg->RX != NULL){
        luat_gpio_cfg_t* _tx_cfg = (pika_dev *)(cfg->TX)->platform_data;
        luat_gpio_cfg_t* _rx_cfg = (pika_dev *)(cfg->RX)->platform_data;
        if (_uart_cfg->id == 2){
            if (_tx_cfg->pin == HAL_GPIO_12 && _rx_cfg->pin == HAL_GPIO_13){
                luat_uart_pre_setup(_uart_cfg->id, 1);
            }
            else if (_tx_cfg->pin == HAL_GPIO_6 && _rx_cfg->pin == HAL_GPIO_7){
                luat_uart_pre_setup(_uart_cfg->id, 2);
            }
            else if (_tx_cfg->pin == HAL_GPIO_10 && _rx_cfg->pin == HAL_GPIO_11){
                luat_uart_pre_setup(_uart_cfg->id, 0);
            }
            else{
                __platform_printf("[ERROR] this UART iomux not support.\r\n");
            }
        }
        else if (_uart_cfg->id == 0){
            if (_tx_cfg->pin == HAL_GPIO_16 && _rx_cfg->pin == HAL_GPIO_17){
                luat_uart_pre_setup(_uart_cfg->id, 1);
            }
            else if (_tx_cfg->pin == HAL_GPIO_14 && _rx_cfg->pin == HAL_GPIO_15){
                luat_uart_pre_setup(_uart_cfg->id, 0);
            }
        }
        else{
            __platform_printf("[ERROR] this UART id not support.\r\n");
        }
        
    }


    if (luat_uart_setup(_uart_cfg) < 0){
        __platform_printf("[ERROR] UART_ioctl_enable failed.\r\n");
        return -1;
    }

    return 0;
}

int pika_hal_platform_UART_ioctl_enable(pika_dev* dev) {
    #if 0
    luat_uart_t* _uart_cfg = dev->platform_data;
    LOG("uart id:%d, baud_rate:%d, data_bits:%d, stop_bits:%d\n",_uart_cfg->id, _uart_cfg->baud_rate, _uart_cfg->data_bits, _uart_cfg->stop_bits);
    if (luat_uart_setup(_uart_cfg) < 0){
        __platform_printf("[ERROR] UART_ioctl_enable failed.\r\n");
        return -1;
    }
    #endif
    return 0;
}

int pika_hal_platform_UART_ioctl_disable(pika_dev* dev) {
    #if 0
    luat_uart_t* _uart_cfg = dev->platform_data;
    if (luat_uart_close(_uart_cfg->id) < 0){
        return -1;
    }
    #endif
    return 0;
}
